---
title: <Puck>
---

# \<Puck\>

Render the Puck editor.

```tsx copy
import { Puck } from "@measured/puck";

const config = {
  components: {},
};

const initialData = {
  content: [],
  root: {},
};

export function Editor() {
  return <Puck config={config} data={initialData} />;
}
```

## Props

| Param                                                 | Example                                            | Type                                                       | Status       |
| ----------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- | ------------ |
| [`config`](#config)                                   | `config: { components: {} }`                       | [Config](/docs/api-reference/configuration/config)         | Required     |
| [`data`](#data)                                       | `data: {}`                                         | [Data](/docs/api-reference/data-model/data)                | Required     |
| [`dnd`](#dnd)                                         | `dnd: {}`                                          | [DndConfig](#dnd-params)                                   | -            |
| [`children`](#children)                               | `children: <Puck.Preview />`                       | ReactNode                                                  | -            |
| [`fieldTransforms`](#fieldtransforms)                 | `fieldTransforms: {text: () => <div />}`           | [FieldTransforms](/docs/api-reference/field-transforms)    | -            |
| [`headerPath`](#headerpath)                           | `headerPath: "/my-page"`                           | String                                                     | -            |
| [`headerTitle`](#headertitle)                         | `headerTitle: "My Page"`                           | String                                                     | -            |
| [`iframe`](#iframe)                                   | `iframe: {}`                                       | [IframeConfig](#iframe-params)                             | -            |
| [`initialHistory`](#initialhistory)                   | `initialHistory: {}`                               | [InitialHistory](#initialhistory-params)                   | -            |
| [`metadata`](#metadata)                               | `metadata: {}`                                     | Object                                                     | -            |
| [`onAction()`](#onactionaction-appstate-prevappstate) | `onAction: (action, appState, prevAppState) => {}` | Function                                                   | -            |
| [`onChange()`](#onchangedata)                         | `onChange: (data) => {}`                           | Function                                                   | -            |
| [`onPublish()`](#onpublishdata)                       | `onPublish: async (data) => {}`                    | Function                                                   | -            |
| [`overrides`](#overrides)                             | `overrides: { header: () => <div /> }`             | [Overrides](/docs/api-reference/overrides)                 | Experimental |
| [`permissions`](#permissions)                         | `permissions: {}`                                  | [Plugin\[\]](/docs/api-reference/plugin)                   | Experimental |
| [`plugins`](#plugins)                                 | `plugins: [myPlugin]`                              | [Plugin\[\]](/docs/api-reference/plugin)                   | Experimental |
| [`ui`](#ui)                                           | `ui: {leftSideBarVisible: false}`                  | [AppState.ui](/docs/api-reference/data-model/app-state#ui) | -            |
| [`viewports`](#viewports)                             | `viewports: [{ width: 1440 }]`                     | [Viewport\[\]](#viewport-params)                           | -            |

## Required props

### `config`

An object describing the available components, fields and more. See the [`Config` docs](/docs/api-reference/configuration/config) for a full reference.

```tsx {4-17} copy
export function Editor() {
  return (
    <Puck
      config={{
        components: {
          HeadingBlock: {
            fields: {
              children: {
                type: "text",
              },
            },
            render: ({ children }) => {
              return <h1>{children}</h1>;
            },
          },
        },
      }}
      // ...
    />
  );
}
```

### `data`

The initial data to render. Cannot be changed once `<Puck>` has been mounted. See the [`Data` docs](/docs/api-reference/data-model/data) for a full reference.

```tsx {4-12} copy
export function Editor() {
  return (
    <Puck
      data={{
        content: [
          {
            props: { children: "Hello, world", id: "id" },
            type: "HeadingBlock",
          },
        ],
        root: {},
      }}
      // ...
    />
  );
}
```

## Optional props

### `children`

Render custom nodes to create [compositional interfaces](/docs/extending-puck/composition).

```tsx {4} copy
export function Editor() {
  return (
    <Puck /*...*/>
      <Puck.Preview />
    </Puck>
  );
}
```

### `dnd`

Configure drag-and-drop behavior.

#### dnd params

| Param                                     | Example                   | Type    | Status |
| ----------------------------------------- | ------------------------- | ------- | ------ |
| [`disableAutoScroll`](#disableautoscroll) | `disableAutoScroll: true` | boolean | -      |

##### `disableAutoScroll`

Disable auto-scroll when the user drags an item near the edge of the preview area.

### `fieldTransforms`

Specify transforms to modify field values before being passed to the editor canvas. Implements the [Field Transforms API](/docs/api-reference/field-transforms).

```tsx {4} copy
export function Editor() {
  return (
    <Puck
      fieldTransforms={{
        text: ({ value }) => <div>{value}</div>, // Wrap all text field values in a div
      }}
      // ...
    />
  );
}
```

### `headerPath`

Set a path to show after the header title

```tsx {4} copy
export function Editor() {
  return (
    <Puck
      headerPath="/my-page"
      // ...
    />
  );
}
```

### `headerTitle`

Set the title shown in the header

```tsx {4} copy
export function Editor() {
  return (
    <Puck
      headerTitle="My page"
      // ...
    />
  );
}
```

### `iframe`

Configure the iframe behaviour.

```tsx {4} copy
export function Editor() {
  return (
    <Puck
      iframe={{ enabled: false }}
      // ...
    />
  );
}
```

#### iframe params

| Param                           | Example                | Type    | Status |
| ------------------------------- | ---------------------- | ------- | ------ |
| [`enabled`](#enabled)           | `enabled: false`       | boolean | -      |
| [`waitForStyles`](#deferrender) | `waitForStyles: false` | boolean | -      |

##### `enabled`

Render the Puck preview within iframe. Defaults to `true`.

Disabling iframes will also disable [viewports](#viewports).

##### `waitForStyles`

Defer rendering of the Puck preview until the iframe styles have loaded, showing a spinner. Defaults to `true`.

### `initialHistory`

Sets the undo/redo Puck history state when using the `usePuck` [history API](/docs/api-reference/puck-api#history).

```tsx showLineNumbers copy {12-15}
const historyState = {
  data: {
    root: {
      props: { title: "My History" },
    },
  },
};

export function Editor() {
  return (
    <Puck
      initialHistory={{
        histories: [{ state: historyState }],
        index: 0,
      }}
      // ...
    />
  );
}
```

#### `initialHistory` params

| Param                       | Example             | Type                                                       | Status   |
| --------------------------- | ------------------- | ---------------------------------------------------------- | -------- |
| [`histories`](#histories)   | `histories: []`     | [History](/docs/api-reference/puck-api#history-params)\[\] | Required |
| [`index`](#index)           | `index: 2`          | Number                                                     | Required |
| [`appendData`](#appenddata) | `appendData: false` | Boolean                                                    | -        |

##### `histories`

An array of histories to reset the Puck state history state to.

##### `index`

The index of the histories to set the user to.

##### `appendData`

Append the Puck [`data`](#data) prop onto the end of [`histories`](#histories). Defaults to `true`.

When `false`, the Puck `data` prop will be ignored but you must specify at least one item in the `histories` array.

### `onAction(action, appState, prevAppState)`

Callback that triggers when Puck dispatches an [action](https://puckeditor.com/docs/api-reference/actions), like `insert` or `set`. Use this to track changes, perform side effects, or sync with external systems.

Receives three arguments:

1. `action`: The action that was dispatched
2. `appState`: The new [`AppState`](/docs/api-reference/data-model/app-state) after the action was applied
3. `prevAppState`: The previous [`AppState`](/docs/api-reference/data-model/app-state) before the action was applied

```tsx {4-8} copy
export function Editor() {
  return (
    <Puck
      onAction={(action, appState, prevAppState) => {
        if (action.type === "insert") {
          console.log("New component was inserted", appState);
        }
      }}
      // ...
    />
  );
}
```

### `metadata`

An object containing additional data provided to each component's [`render`](/docs/api-reference/configuration/component-config#renderprops) and [`resolveData`](/docs/api-reference/configuration/component-config#resolvedatadata-params) functions.

```tsx {4,8} copy
export function Editor() {
  return (
    <Puck
      metadata={{ title: "Hello, world" }}
      config={{
        HeadingBlock: {
          render: ({ puck }) => {
            return <h1>{puck.metadata.title}</h1>; // "Hello, world"
          },
        },
      }}
      // ...
    />
  );
}
```

### `onChange(data)`

Callback that triggers when the user makes a change.

Receives a single [`Data`](/docs/api-reference/data-model/data) arg.

```tsx {4-6} copy
export function Editor() {
  return (
    <Puck
      onChange={(data) => {
        console.log("Puck data was updated", data);
      }}
      // ...
    />
  );
}
```

### `onPublish(data)`

Callback that triggers when the user hits the "Publish" button. Use this to save the Puck data to your database.

Receives a single [`Data`](/docs/api-reference/data-model/data) arg.

```tsx {4-9} copy
export function Editor() {
  return (
    <Puck
      onPublish={async (data) => {
        await fetch("/my-api", {
          method: "post",
          body: JSON.stringify({ data }),
        });
      }}
      // ...
    />
  );
}
```

### `overrides`

An [`Overrides`](/docs/api-reference/overrides) object defining custom render methods for various parts of the Puck UI.

```tsx {4-6} copy
export function Editor() {
  return (
    <Puck
      overrides={{
        header: () => <div />,
      }}
      // ...
    />
  );
}
```

### `permissions`

Set the global [permissions](/docs/api-reference/permissions) for the Puck instance to toggle Puck functionality.

```tsx {4-6} copy
export function Editor() {
  return (
    <Puck
      permissions={{
        delete: false, // Prevent deletion of all components
      }}
      // ...
    />
  );
}
```

### `plugins`

An array of plugins to enhance Puck's behaviour. See the [Plugin API reference](/docs/api-reference/plugin).

```tsx {6} copy
import headingAnalyzer from "@measured/puck-plugin-heading-analyzer";

export function Editor() {
  return (
    <Puck
      plugins={[headingAnalyzer]}
      // ...
    />
  );
}
```

### `ui`

Set the initial application UI state. See [`AppState.ui`](/docs/api-reference/data-model/app-state#ui).

```tsx {5} copy
export function Editor() {
  return (
    <Puck
      // Hide the left side bar by default
      ui={{ leftSideBarVisible: false }}
      // ...
    />
  );
}
```

### `viewports`

Configure the viewports available to the user, rendered as an iframe. Puck will select the most appropriate initial viewport based on the user's window size, unless otherwise specified via the [`ui`](#ui) prop.

```tsx {4-8} copy
export function Editor() {
  return (
    <Puck
      viewports={[
        {
          width: 1440,
        },
      ]}
      // ...
    />
  );
}
```

#### Viewport params

| Param               | Example           | Type                                                     | Status   |
| ------------------- | ----------------- | -------------------------------------------------------- | -------- |
| [`width`](#width)   | `width: 1440`     | number                                                   | Required |
| [`height`](#height) | `height: 968`     | number \| `"auto"`                                       | -        |
| [`icon`](#icon)     | `icon: "Monitor"` | `"Smartphone"` \| `"Tablet"` \| `"Monitor"` \| ReactNode | -        |
| [`label`](#label)   | `label: "iPhone"` | string                                                   | -        |

##### `width`

The width of the viewport.

##### `height`

An optional height for the viewport. Defaults to `auto`, which will fit to the window.

##### `label`

An optional label for the viewport. This is used for browser tooltip.

##### `icon`

The icon to show in the viewport switcher. Can be:

- `"Smartphone"`
- `"Tablet"`
- `"Monitor"`
- ReactNode

Puck uses [Lucide icons](https://lucide.dev/icons/). You can use [lucide-react](https://lucide.dev/guide/packages/lucide-react) to choose a similar icon, if desired.

#### Default viewports

By default, Puck exposes small, medium and large viewports based on common viewport sizes.

```json
[
  {
    "width": 360,
    "height": "auto",
    "icon": "Smartphone",
    "label": "Small"
  },
  {
    "width": 768,
    "height": "auto",
    "icon": "Tablet",
    "label": "Medium"
  },
  {
    "width": 1280,
    "height": "auto",
    "icon": "Monitor",
    "label": "Large"
  }
]
```
